package org.idea.spring.datasource.ibernate.factorybean;

import com.alibaba.druid.pool.DruidDataSource;
import org.idea.spring.datasource.bean.User;
import org.idea.spring.datasource.ibernate.ISelect;
import org.idea.spring.datasource.ibernate.dao.UserDao;
import org.idea.spring.datasource.ibernate.handler.IResultSetHandler;
import org.idea.spring.datasource.ibernate.handler.ResultSetHandler;
import org.springframework.beans.factory.FactoryBean;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * @Author linhao
 * @Date created in 4:11 下午 2021/5/17
 */
public class UserMapperFactoryBean implements FactoryBean {

    private DruidDataSource druidDataSource;

    public UserMapperFactoryBean(DruidDataSource druidDataSource) {
        this.druidDataSource = druidDataSource;
    }

    @Override
    public Object getObject() throws Exception {
        return Proxy.newProxyInstance(UserDao.class.getClassLoader(), new Class[]{UserDao.class}, new UserMapperProxy(druidDataSource));
    }

    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

class UserMapperProxy implements InvocationHandler {

    private DruidDataSource druidDataSource;

    public UserMapperProxy(DruidDataSource druidDataSource) {
        this.druidDataSource = druidDataSource;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        ISelect iSelect = method.getAnnotation(ISelect.class);
        if (iSelect != null) {
            String sql = iSelect.value();
            if(java.util.List.class.equals(method.getReturnType())) {
                return this.doQuerySql(sql);
            } else {
                return this.doQueryObjSql(sql);
            }
        }
        return null;
    }

    /**
     * 临时兼容没有参数类型sql查询
     *
     * @param querySql
     * @return
     * @throws SQLException
     */
    private List doQuerySql(String querySql) throws SQLException {
        Connection connection = druidDataSource.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(querySql);
        IResultSetHandler iResultSetHandler = new ResultSetHandler(User.class);
        ResultSet resultSet = preparedStatement.executeQuery();
        List<Object> resultList = iResultSetHandler.handleList(resultSet);
        connection.close();
        return resultList;
    }

    /**
     * 临时兼容没有参数类型sql查询
     *
     * @param querySql
     * @return
     * @throws SQLException
     */
    private Object doQueryObjSql(String querySql) throws SQLException {
        Connection connection = druidDataSource.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(querySql);
        IResultSetHandler iResultSetHandler = new ResultSetHandler(User.class);
        ResultSet resultSet = preparedStatement.executeQuery();
        Object result = iResultSetHandler.handleSingle(resultSet);
        connection.close();
        return result;
    }
}
